home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / msysjour / vol04 / 02a / mdi / mdi2.c < prev    next >
C/C++ Source or Header  |  1988-12-06  |  24KB  |  808 lines

  1. /*
  2.  * MDI2.C - Child Window Routines
  3.  *
  4.  * LANGUAGE      : Microsoft C5.1
  5.  * MODEL         : medium
  6.  * ENVIRONMENT   : Microsoft Windows 2.1 SDK
  7.  * STATUS        : operational
  8.  *
  9.  * This module contains all the MDI code to handle the activation
  10.  * sequence for and switching activation between the MDI document
  11.  * windows.  It also contains the maximizing and restoring of document
  12.  * windows and especially the activation and switching between them.
  13.  * It also contains the code for the unhide dialog box.
  14.  *
  15.  * Developed by:
  16.  *   Geoffrey Nicholls
  17.  *   Kevin P. Welch
  18.  *
  19.  * (C) Copyright 1988
  20.  * Eikon Systems, Inc.
  21.  * 989 E. Hillsdale Blvd, Suite 260
  22.  * Foster City  CA  94404
  23.  *
  24.  */
  25.  
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <windows.h>
  29.  
  30. #include "mdi.h"
  31.  
  32. /* */
  33.  
  34. /*
  35.  * MdiDestroyChildWindow( hwndChild ) : void;
  36.  *
  37.  *    hwndChild      Handle of document window
  38.  *
  39.  * This routine is called when a document window is closing.  It picks
  40.  * a new active document window and activates it.  If no other document
  41.  * window is available (visible) then it restores the original menu
  42.  * on the MDI desktop and sets the focus to the desktop.
  43.  *
  44.  */
  45.  
  46. void MdiDestroyChildWindow( 
  47.    HWND        hwndChild )
  48. {
  49.    HMENU       hmenuMain;        /* MDI desktop menu */
  50.    HMENU       hmenuOld;         /* Document menu */
  51.    HWND        hwndNext;         /* Next active document window */
  52.    HWND        hwndMain;         /* Handle to MDI desktop */
  53.  
  54.    /* Remove ourselves from the menus */
  55.    MdiRemoveWindowFromMenu( hwndChild, TRUE );
  56.  
  57.    /* Let's choose a new MDI child to be active */
  58.    hwndMain = GetParent( hwndChild );
  59.    hwndNext = MdiChooseNewActiveChild( hwndChild );
  60.    if ( hwndNext )
  61.    {
  62.       /* Make this MDI child active */
  63.       if ( GetProp( hwndMain, PROP_ZOOM ) )
  64.       {
  65.          MdiSwitchZoom( hwndNext, hwndChild );
  66.       }
  67.       MdiActivateChild( hwndNext, FALSE );
  68.  
  69.    }
  70.    else
  71.    {
  72.       /* No other MDI child visible */
  73.       if ( GetProp( hwndMain, PROP_ZOOM ) )
  74.       {
  75.          SetProp( hwndMain, PROP_ZOOM, FALSE );
  76.          MdiRestoreChild( hwndChild, FALSE );
  77.       }
  78.  
  79.       /* Back to bare-bones menu */
  80.       hmenuOld = GetMenu( hwndMain );
  81.       hmenuMain = GetProp( hwndMain, PROP_MAINMENU );
  82.       MdiWindowMenu( hwndMain, hmenuMain, TRUE );
  83.       SetMenu( hwndMain, hmenuMain );
  84.       MdiWindowMenu( hwndMain, hmenuOld, FALSE );
  85.       SetProp( hwndMain, PROP_ACTIVE, NULL );
  86.  
  87.       /* Focus back to parent */
  88.       SetFocus( hwndMain );
  89.    }
  90.  
  91.    /* Ensure menu updated */
  92.    DrawMenuBar( hwndMain );
  93. }
  94.  
  95. /* */
  96.  
  97. /*
  98.  * MdiActivateChild( hwndChild, bHidden ) : void;
  99.  *
  100.  *    hwndChild      Handle to document window
  101.  *    bHidden        Was document previous hidden?
  102.  *
  103.  * Bring a specific document window to the fore.  Give it the correct
  104.  * title bar, bring it to the top, put the matching menu on the MDI
  105.  * desktop, etc.
  106.  *
  107.  */
  108.  
  109. void MdiActivateChild( 
  110.    HWND        hwndChild,
  111.    BOOL        bHidden )
  112. {
  113.    HMENU       hmenuOld;         /* Previous document's menu */
  114.    HMENU       hmenuNew;         /* This document's menu */
  115.    HMENU       hmenuWindow;      /* WINDOW submenu */
  116.    HWND        hwndActive;       /* Handle to previous document */
  117.    HWND        hwndMain;         /* Handle to MDI desktop */
  118.    LONG        lStyle;           /* Style of document window */
  119.  
  120.    /* Check if this MDI child already activated */
  121.    hwndMain = GetParent( hwndChild );
  122.    lStyle = GetWindowLong( hwndChild, GWL_STYLE );
  123.    if ( ( lStyle & WS_MAXIMIZEBOX ) == 0 )
  124.    {
  125.       /* Change the title bar color */
  126.       SendMessage( hwndChild, WM_NCACTIVATE, TRUE, 0L );
  127.  
  128.       /* Add system menu & maximize arrow to title bar */
  129.       SetWindowLong( hwndChild,
  130.          GWL_STYLE,
  131.          lStyle | WS_MAXIMIZEBOX | WS_SYSMENU );
  132.  
  133.       /* Make changes visible */
  134.       if ( bHidden )
  135.       {
  136.          BringWindowToTop( hwndChild );
  137.          ShowWindow( hwndChild, SW_SHOW );
  138.       }
  139.       else
  140.       {
  141.          /* Bring to top & draw nonclient area */
  142.          SetWindowPos( hwndChild,
  143.             NULL,
  144.             0, 0, 0, 0,
  145.             SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE );
  146.       }
  147.  
  148.       /* Update this child */
  149.       hwndActive = GetProp( hwndMain, PROP_ACTIVE );
  150.       if ( hwndActive != hwndChild )
  151.       {
  152.          /* Remove traces of activeness from previous MDI child */
  153.          if ( hwndActive && hwndActive != hwndChild )
  154.          {
  155.             MdiDeactivateChild( hwndActive );
  156.          }
  157.  
  158.          /* Install correct menu for this MDI child */
  159.          hmenuNew = GetProp( hwndChild, PROP_CHILDMENU );
  160.          hmenuOld = GetMenu( hwndMain );
  161.          MdiWindowMenu( hwndMain, hmenuNew, TRUE );
  162.          SetMenu( hwndMain, hmenuNew );
  163.          MdiWindowMenu( hwndMain, hmenuOld, FALSE );
  164.          DrawMenuBar( hwndMain );
  165.  
  166.          /* This child now active */
  167.          SetProp( hwndMain, PROP_ACTIVE, hwndChild );
  168.       }
  169.  
  170.       /* Check our menu on the WINDOW menu */
  171.       hmenuWindow = GetProp( hwndMain, PROP_WINDOWMENU );
  172.       CheckMenuItem( hmenuWindow,
  173.          GetProp( hwndChild, PROP_MENUID ),
  174.          MF_CHECKED | MF_BYCOMMAND );
  175.  
  176.       /* Should have focus */
  177.       if ( GetFocus( ) != hwndChild )
  178.       {
  179.          SetFocus( hwndChild );
  180.       }
  181.    }
  182. }
  183.  
  184. /* */
  185.  
  186. /*
  187.  * MdiActivateNextChild( hwndChild ) : void;
  188.  *
  189.  *    hwndChild      Handle to current document
  190.  *
  191.  * Activate the next document in the internal windows queue.
  192.  * This function reached via <ctrl><F6> only.
  193.  *
  194.  */
  195.  
  196. void MdiActivateNextChild( 
  197.    HWND        hwndChild )
  198. {
  199.    HWND        hwndActive;       /* Handle to previous document */
  200.    HWND        hwndIter;         /* Iterating document windows */
  201.    HWND        hwndMain;         /* Handle to MDI desktop */
  202.  
  203.    for ( hwndIter = GetWindow( hwndChild, GW_HWNDNEXT );
  204.       hwndIter != NULL;
  205.       hwndIter = GetWindow( hwndIter, GW_HWNDNEXT ) )
  206.    {
  207.       /*
  208.       ** Get next visible, MDI child in internal windows chain
  209.       */
  210.       if ( GetProp(hwndIter, PROP_ISMDI) && IsWindowVisible(hwndIter) )
  211.       {
  212.          break;
  213.       }
  214.    }
  215.  
  216.    /* Did we find another MDI child? */
  217.    if ( hwndIter )
  218.    {
  219.       hwndMain = GetParent( hwndIter );
  220.       hwndActive = GetProp( hwndMain, PROP_ACTIVE );
  221.       if ( GetProp( hwndMain, PROP_ZOOM ) )
  222.       {
  223.          /* Activate the new one */
  224.          MdiSwitchZoom( hwndIter, hwndActive );
  225.          MdiActivateChild( hwndIter, FALSE );
  226.  
  227.          /* Place window at end of internal windows queue */
  228.          SetWindowPos( hwndChild,
  229.             ( HWND ) 1,
  230.             0, 0, 0, 0,
  231.             SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
  232.       }
  233.       else
  234.       {
  235.          /* Place window at end of internal windows queue */
  236.          SetWindowPos( hwndChild,
  237.             ( HWND ) 1,
  238.             0, 0, 0, 0,
  239.             SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
  240.  
  241.          /* Activate the new one */
  242.          MdiActivateChild( hwndIter, FALSE );
  243.       }
  244.    }
  245. }
  246.  
  247. /* */
  248.  
  249. /*
  250.  * MdiActivatePrevChild( hwndChild ) : void;
  251.  *
  252.  *    hwndChild      Handle to current document
  253.  *
  254.  * Activate the previous document in the internal windows queue.
  255.  * This function reached via <ctrl><shift><F6> only.
  256.  *
  257.  */
  258.  
  259. void MdiActivatePrevChild( 
  260.    HWND        hwndChild )
  261. {
  262.    HWND        hwndActive;       /* Handle to previous document */
  263.    HWND        hwndIter;         /* Iterate document windows */
  264.    HWND        hwndMain;         /* Handle to MDI desktop */
  265.  
  266.    for ( hwndIter = GetWindow( hwndChild, GW_HWNDLAST );
  267.       hwndIter != NULL;
  268.       hwndIter = GetWindow( hwndIter, GW_HWNDPREV ) )
  269.    {
  270.       /*
  271.       ** Get prev visible, MDI window in internal windows chain
  272.       */
  273.       if ( GetProp(hwndIter, PROP_ISMDI) && IsWindowVisible(hwndIter) )
  274.       {
  275.          break;
  276.       }
  277.    }
  278.  
  279.    /* Did we find another MDI child? */
  280.    if ( hwndIter )
  281.    {
  282.       /* Activate the new one */
  283.       hwndMain = GetParent( hwndChild );
  284.       hwndActive = GetProp( hwndMain, PROP_ACTIVE );
  285.       if ( GetProp( hwndMain, PROP_ZOOM ) )
  286.       {
  287.          MdiSwitchZoom( hwndIter, hwndActive );
  288.       }
  289.       MdiActivateChild( hwndIter, FALSE );
  290.    }
  291. }
  292.  
  293. /* */
  294.  
  295. /*
  296.  * MdiDectivateChild( hwndChild ) : void;
  297.  *
  298.  *    hwndChild      Handle to document window
  299.  *
  300.  * Put a specific document window to the back.  Either another
  301.  * document is being activated or the application is losing focus.
  302.  *
  303.  */
  304.  
  305. void MdiDeactivateChild( 
  306.    HWND        hwndChild )
  307. {
  308.    LONG        lStyle;           /* Style of document window */
  309.  
  310.    /* Check if this MDI child already deactivated */
  311.    lStyle = GetWindowLong( hwndChild, GWL_STYLE );
  312.    if ( lStyle & WS_MAXIMIZEBOX )
  313.    {
  314.       /* Change the title bar color */
  315.       SendMessage( hwndChild, WM_NCACTIVATE, FALSE, 0L );
  316.  
  317.       /* Add system menu & maximize arrow to title bar */
  318.       SetWindowLong( hwndChild,
  319.          GWL_STYLE,
  320.          lStyle & ~( WS_MAXIMIZEBOX | WS_SYSMENU ) );
  321.  
  322.       SetWindowPos( hwndChild,
  323.          NULL,
  324.          0, 0, 0, 0,
  325.          SWP_DRAWFRAME  | SWP_NOACTIVATE  | SWP_NOMOVE
  326.                         | SWP_NOSIZE      | SWP_NOZORDER );
  327.    }
  328.  
  329.    /* Remove check mark for our window */
  330.    CheckMenuItem( GetProp( GetParent( hwndChild ), PROP_WINDOWMENU ),
  331.       GetProp( hwndChild, PROP_MENUID ),
  332.       MF_UNCHECKED | MF_BYCOMMAND );
  333. }
  334.  
  335. /* */
  336.  
  337. /*
  338.  * MdiZoomChild( hwndChild ) : void;
  339.  *
  340.  *    hwndChild      Handle to document
  341.  *
  342.  * Bring the specific document to full client area display.  A default
  343.  * maximize puts the border and title bar in the client area.  This
  344.  * routine matches the document client area to the MDI desktop client
  345.  * area.  It also appends the document title to the MDI desktop
  346.  * title.
  347.  *
  348.  */
  349.  
  350. void MdiZoomChild( 
  351.    HWND        hwndChild )
  352. {
  353.    char        szTitle[128];     /* Text for title bar */
  354.    char        szMain[128];      /* Text on non-zoomed title bar */
  355.    char        szChild[128];     /* Text for document title bar */
  356.    HWND        hwndMain;         /* Handle to MDI desktop */
  357.    LONG        lStyle;           /* Style of document window */
  358.    RECT        rcClient;         /* Client area of MDI desktop */
  359.  
  360.    /* Change the menu */
  361.    hwndMain = GetParent( hwndChild );
  362.    MdiZoomMenu( hwndChild );
  363.    DrawMenuBar( hwndMain );
  364.  
  365.    /* Change the title bar */
  366.    GetAtomName( GetProp( hwndMain, PROP_TITLE ),
  367.       szMain,
  368.       sizeof(szMain) );
  369.    GetWindowText( hwndChild, szChild, sizeof( szChild ) );
  370.    sprintf( szTitle, "%s - %s", szMain, szChild );
  371.    SetWindowText( hwndMain, szTitle );
  372.  
  373.    /* Remember where this window was in the client area */
  374.    GetWindowRect( hwndChild, &rcClient );
  375.    ScreenToClient( hwndMain, ( LPPOINT ) &rcClient+0 );
  376.    ScreenToClient( hwndMain, ( LPPOINT ) &rcClient+1 );
  377.  
  378.    SetProp( hwndChild, PROP_LEFT, rcClient.left );
  379.    SetProp( hwndChild, PROP_TOP, rcClient.top );
  380.    SetProp( hwndChild, PROP_WIDTH, rcClient.right - rcClient.left );
  381.    SetProp( hwndChild, PROP_HEIGHT, rcClient.bottom - rcClient.top );
  382.  
  383.    /* Bring the window to use the whole client area */
  384.    GetClientRect( hwndMain, &rcClient );
  385.    lStyle = GetWindowLong( hwndChild, GWL_STYLE );
  386.    AdjustWindowRect( &rcClient, lStyle, FALSE );
  387.    SetWindowPos( hwndChild,
  388.       ( HWND ) NULL,
  389.       rcClient.left, rcClient.top,
  390.       rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
  391.       0 );
  392.  
  393.    /* Mark maximized in the window style */
  394.    SetWindowLong( hwndChild, GWL_STYLE, lStyle | WS_MAXIMIZE );
  395. }
  396.  
  397. /* */
  398.  
  399. /*
  400.  * MdiRestoreChild( hwndChild, bHidden ) : void;
  401.  *
  402.  *    hwndChild      Handle to document
  403.  *    bShowMove      Should we show this occurance or hide it
  404.  *
  405.  * Bring the specific document back from full client area display.
  406.  * This routine places the document window where it was before the
  407.  * maximize by remembering the position in property lists.  It also
  408.  * restores the original title to the MDI desktop titlebar.
  409.  *
  410.  */
  411.  
  412. void MdiRestoreChild( 
  413.    HWND        hwndChild,
  414.    BOOL        bShowMove )
  415. {
  416.    char        szMain[128];      /* Text on non-zoomed title bar */
  417.    HWND        hwndMain;         /* Handle to MDI desktop */
  418.    LONG        lStyle;           /* Style of document window */
  419.  
  420.    /* Change the menu */
  421.    hwndMain = GetParent( hwndChild );
  422.    MdiRestoreMenu( hwndChild );
  423.    DrawMenuBar( hwndMain );
  424.  
  425.    /* Reflect in the title bar of the main app */
  426.    GetAtomName( GetProp( hwndMain, PROP_TITLE ),
  427.       szMain,
  428.       sizeof( szMain ) );
  429.    SetWindowText( hwndMain, szMain );
  430.  
  431.    /* Mark normal size in the window style */
  432.    lStyle = GetWindowLong( hwndChild, GWL_STYLE );
  433.    SetWindowLong( hwndChild, GWL_STYLE, lStyle & ~WS_MAXIMIZE );
  434.  
  435.    /* Are we HIDING the last visible MDI child */
  436.    if ( !bShowMove )
  437.    {
  438.       ShowWindow( hwndChild, SW_HIDE );
  439.    }
  440.  
  441.    /* Move the window back to where it was before it zoomed */
  442.    /* Also place in beginning of internal windows queue */
  443.    SetWindowPos( hwndChild,
  444.       ( HWND ) NULL,
  445.       GetProp( hwndChild, PROP_LEFT ),
  446.       GetProp( hwndChild, PROP_TOP ),
  447.       GetProp( hwndChild, PROP_WIDTH ),
  448.       GetProp( hwndChild, PROP_HEIGHT ),
  449.       0 );
  450. }
  451.  
  452. /* */
  453.  
  454. /*
  455.  * MdiSwitchZoom( hwndNew, hwndCur ) : void;
  456.  *
  457.  *    hwndNew        Handle to new document
  458.  *    hwndCur        Handle to previous document
  459.  *
  460.  * This routine switches activation between two document windows
  461.  * when the original document window is maximized.  Every time document
  462.  * windows switch, the sequence of activation is important.  When the
  463.  * documents are maximized, it is crucial to not follow the ordinary
  464.  * sequence, otherwise it is possible to see the other, non-maximized
  465.  * document windows briefly before the new document window covers
  466.  * the client area.
  467.  *
  468.  */
  469.  
  470. void MdiSwitchZoom( 
  471.    HWND        hwndNew,
  472.    HWND        hwndCur )
  473. {
  474.    char        szTitle[128];     /* Text for title bar */
  475.    char        szMain[128];      /* Text on non-zoomed title bar */
  476.    char        szChild[128];     /* Text for document title bar */
  477.    HWND        hwndMain;         /* Handle to MDI desktop */
  478.    LONG        lStyle;           /* Style of document window */
  479.    RECT        rcClient;         /* Client area of MDI desktop */
  480.  
  481.    /* Change the title bar */
  482.    hwndMain = GetParent( hwndCur );
  483.    GetAtomName( GetProp( hwndMain, PROP_TITLE ),
  484.       szMain,
  485.       sizeof(szMain) );
  486.    GetWindowText( hwndNew, szChild, sizeof( szChild ) );
  487.    sprintf( szTitle, "%s - %s", szMain, szChild );
  488.    SetWindowText( hwndMain, szTitle );
  489.  
  490.    /* NEW WINDOW */
  491.  
  492.    /* Remember where this window was in the client area */
  493.    GetWindowRect( hwndNew, &rcClient );
  494.    ScreenToClient( hwndMain, ( LPPOINT ) &rcClient+0 );
  495.    ScreenToClient( hwndMain, ( LPPOINT ) &rcClient+1 );
  496.  
  497.    SetProp( hwndNew, PROP_LEFT, rcClient.left );
  498.    SetProp( hwndNew, PROP_TOP, rcClient.top );
  499.    SetProp( hwndNew, PROP_WIDTH, rcClient.right - rcClient.left );
  500.    SetProp( hwndNew, PROP_HEIGHT, rcClient.bottom - rcClient.top );
  501.  
  502.    /* Reposition the new window */
  503.    GetClientRect( GetParent( hwndNew ), &rcClient );
  504.    lStyle = GetWindowLong( hwndNew, GWL_STYLE );
  505.    AdjustWindowRect( &rcClient, lStyle, FALSE );
  506.    SetWindowPos( hwndNew,
  507.       ( HWND ) NULL,
  508.       rcClient.left, rcClient.top,
  509.       rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
  510.       SWP_NOREDRAW | SWP_NOACTIVATE );
  511.  
  512.    /* Mark maximized in the window style */
  513.    SetWindowLong( hwndNew, GWL_STYLE, lStyle | WS_MAXIMIZE );
  514.  
  515.    /* Update menu */
  516.    MdiZoomMenu( hwndNew );
  517.  
  518.    /* Display the window */
  519.    ShowWindow( hwndNew, SW_SHOW );
  520.  
  521.    /* Client area is of the old window */
  522.    InvalidateRect( hwndNew, ( LPRECT ) NULL, TRUE );
  523.  
  524.    /* OLD WINDOW */
  525.  
  526.    /* Mark normal size in the window style */
  527.    lStyle = GetWindowLong( hwndCur, GWL_STYLE );
  528.    SetWindowLong( hwndCur, GWL_STYLE, lStyle & ~WS_MAXIMIZE );
  529.  
  530.    /* Move the window back to where it was before it zoomed */
  531.    SetWindowPos( hwndCur,
  532.       ( HWND ) NULL,
  533.       GetProp( hwndCur, PROP_LEFT ),
  534.       GetProp( hwndCur, PROP_TOP ),
  535.       GetProp( hwndCur, PROP_WIDTH ),
  536.       GetProp( hwndCur, PROP_HEIGHT ),
  537.       SWP_NOACTIVATE | SWP_NOZORDER );
  538.  
  539.    /* Update menu */
  540.    MdiRestoreMenu( hwndCur );
  541. }
  542.  
  543. /* */
  544.  
  545. /*
  546.  * MdiUnhideChild( hwndChild ) : void;
  547.  *
  548.  *    hwndChild      Handle to document
  549.  *
  550.  * Decide on the next document to activate when the current one is
  551.  * hidden or closed.
  552.  *
  553.  */
  554.  
  555. HWND MdiChooseNewActiveChild( 
  556.    HWND        hwndChild )
  557. {
  558.    HWND        hwndIter;         /* Iterate document windows */
  559.  
  560.    /* Choose a new child window for activation */
  561.    for ( hwndIter = GetWindow( hwndChild, GW_HWNDFIRST );
  562.       hwndIter != NULL;
  563.       hwndIter = GetWindow( hwndIter, GW_HWNDNEXT ) )
  564.    {
  565.       /*
  566.       ** Get next visible, MDI child in internal windows chain
  567.       ** that's not the current one.
  568.       */
  569.       if ( GetProp( hwndIter, PROP_ISMDI )
  570.          && hwndIter != hwndChild
  571.          && IsWindowVisible( hwndIter ) )
  572.       {
  573.          break;
  574.       }
  575.    }
  576.    return hwndIter;
  577. }
  578.  
  579. /* */
  580.  
  581. /*
  582.  * MdiHideChild( hwndChild ) : void;
  583.  *
  584.  *    hwndChild      Handle to document
  585.  *
  586.  * Hide a specific document from view.  This routine also handles
  587.  * activating the next appropriate document window.  If none exist
  588.  * then it restores the original menu on the MDI desktop and sets
  589.  * the focus to the desktop.
  590.  *
  591.  */
  592.  
  593. void MdiHideChild( 
  594.    HWND        hwndChild )
  595. {
  596.    int         iCount;           /* Number of hidden documents */
  597.    HMENU       hmenuMain;        /* MDI desktop menu */
  598.    HMENU       hmenuOld;         /* Document menu */
  599.    HWND        hwndMain;         /* Handle to MDI desktop */
  600.    HWND        hwndNext;         /* Next active document window */
  601.  
  602.    /* One less visible MDI child */
  603.    hwndMain = GetParent( hwndChild );
  604.    iCount = GetProp( hwndMain, PROP_HIDDEN );
  605.    SetProp( hwndMain, PROP_HIDDEN, ++iCount );
  606.  
  607.    /* We're no longer around */
  608.    MdiDeactivateChild( hwndChild );
  609.    MdiRemoveWindowFromMenu( hwndChild, FALSE );
  610.  
  611.    /* Find us a new active MDI child */
  612.    hwndNext = MdiChooseNewActiveChild( hwndChild );
  613.  
  614.    /* Juggle the windows around */
  615.    if ( hwndNext )
  616.    {
  617.       /* There is another window to put up */
  618.       if ( GetProp( hwndMain, PROP_ZOOM ) )
  619.       {
  620.          MdiSwitchZoom( hwndNext, hwndChild );
  621.       }
  622.       ShowWindow( hwndChild, SW_HIDE );
  623.       MdiActivateChild( hwndNext, FALSE );
  624.    }
  625.    else
  626.    {
  627.       /* Hiding the last MDI child */
  628.       if ( GetProp( hwndMain, PROP_ZOOM ) )
  629.       {
  630.          SetProp( hwndMain, PROP_ZOOM, FALSE );
  631.          MdiRestoreChild( hwndChild, FALSE );
  632.       }
  633.       ShowWindow( hwndChild, SW_HIDE );
  634.  
  635.       /* Back to bare-bones menu */
  636.       hmenuOld = GetMenu( hwndMain );
  637.       hmenuMain = GetProp( hwndMain, PROP_MAINMENU );
  638.       MdiWindowMenu( hwndMain, hmenuMain, TRUE );
  639.       SetMenu( hwndMain, hmenuMain );
  640.       MdiWindowMenu( hwndMain, hmenuOld, FALSE );
  641.       SetProp( hwndMain, PROP_ACTIVE, NULL );
  642.  
  643.       /* Focus back to parent */
  644.       SetFocus( hwndMain );
  645.    }
  646. }
  647.  
  648. /* */
  649.  
  650. /*
  651.  * MdiUnhideChild( hwndChild ) : void;
  652.  *
  653.  *    hwndChild      Handle to document
  654.  *
  655.  * Bring a previous hidden document back to view.
  656.  *
  657.  */
  658.  
  659. void MdiUnhideChild( 
  660.    HWND        hwndChild )
  661. {
  662.    int         iCount;           /* Number of hidden documents */
  663.    HWND        hwndMain;         /* Handle to MDI desktop */
  664.  
  665.    /* One more visible MDI child */
  666.    hwndMain = GetParent( hwndChild );
  667.    iCount = GetProp( hwndMain, PROP_HIDDEN );
  668.    SetProp( hwndMain, PROP_HIDDEN, --iCount );
  669.  
  670.    /* Adjust menu */
  671.    MdiReinsertWindowInMenu( hwndChild );
  672.  
  673.    /* We're activating */
  674.    if ( GetProp( hwndMain, PROP_ZOOM ) )
  675.    {
  676.       MdiSwitchZoom( hwndChild, GetProp( hwndMain, PROP_ACTIVE ) );
  677.    }
  678.    MdiActivateChild( hwndChild, TRUE );
  679. }
  680.  
  681. /* */
  682.  
  683. /*
  684.  * MdiDlgUnhide( hwndUnhide, message, wParam, lParam ) : int;
  685.  *
  686.  *    hwndUnhide     Handle to dialog box
  687.  *    message        Current message
  688.  *    wParam         Word parameter to the message
  689.  *    lParam         Long parameter to the message
  690.  *
  691.  * Handle the UNHIDE dialog box.  This routine assumes that no two
  692.  * document windows have the same title.  When the user selects a title
  693.  * from the listbox, this routine iterates the existing documents for
  694.  * a window with the same title.  It then unhides that one.
  695.  *
  696.  */
  697.  
  698. int FAR PASCAL MdiDlgUnhide(
  699.    HWND        hwndUnhide,
  700.    unsigned    message,
  701.    WORD        wParam,
  702.    LONG        lParam )
  703. {
  704.    char        sTitle[80];       /* Title of document windows */
  705.    char        sSelected[80];    /* Selected document in list box */
  706.    int         iIndex;           /* Index into list box */
  707.    HWND        hwndIter;         /* Iterate document windows */
  708.    HWND        hwndMain;         /* Handle to MDI desktop */
  709.  
  710.    switch ( message )
  711.    {
  712.    case WM_INITDIALOG:
  713.       /* Put the titles of the MDI children in the list box */
  714.       hwndMain = GetParent( hwndUnhide );
  715.       for ( hwndIter = GetTopWindow( hwndMain );
  716.          hwndIter != NULL;
  717.          hwndIter = GetWindow( hwndIter, GW_HWNDNEXT ) )
  718.       {
  719.          /* Ignore non-MDI or visible children */
  720.          if ( !GetProp( hwndIter, PROP_ISMDI )
  721.             || IsWindowVisible( hwndIter ) )
  722.          {
  723.             continue;
  724.          }
  725.  
  726.          /* A potential window to unhide */
  727.          GetWindowText( hwndIter, sTitle, sizeof( sTitle ) );
  728.          SendDlgItemMessage( hwndUnhide,
  729.             DLGUNHIDE_LB,
  730.             LB_ADDSTRING,
  731.             0,
  732.             ( LONG ) ( LPSTR ) sTitle );
  733.       }
  734.  
  735.       /* Select the first MDI child in the list box */
  736.       SendDlgItemMessage( hwndUnhide, DLGUNHIDE_LB, LB_SETCURSEL, 0, 0L );
  737.       return TRUE;
  738.    
  739.    case WM_COMMAND:
  740.       switch( wParam )
  741.       {
  742.       case IDOK:
  743.          /* Which MDI child is selected in the list box? */
  744.          iIndex = ( int ) SendDlgItemMessage( hwndUnhide,
  745.             DLGUNHIDE_LB,
  746.             LB_GETCURSEL,
  747.             0,
  748.             0L );
  749.          if ( iIndex == LB_ERR )
  750.          {
  751.             EndDialog( hwndUnhide, NULL );
  752.             break;
  753.          }
  754.  
  755.          /* Get the title of the MDI child selected */
  756.          SendDlgItemMessage( hwndUnhide,
  757.             DLGUNHIDE_LB,
  758.             LB_GETTEXT,
  759.             iIndex,
  760.             ( LONG ) ( LPSTR ) sSelected );
  761.  
  762.          /* Compare the title to all our MDI children */
  763.          hwndMain = GetParent( hwndUnhide );
  764.          for ( hwndIter = GetTopWindow( hwndMain );
  765.             hwndIter != NULL;
  766.             hwndIter = GetWindow( hwndIter, GW_HWNDNEXT ) )
  767.          {
  768.             /* Ignore non-MDI or visible children */
  769.             if ( !GetProp( hwndIter, PROP_ISMDI )
  770.                || IsWindowVisible( hwndIter ) )
  771.             {
  772.                continue;
  773.             }
  774.  
  775.             /* Found one that's hidden */
  776.             GetWindowText( hwndIter, sTitle, sizeof( sTitle ) );
  777.             if ( strcmp( sTitle, sSelected ) == 0 )
  778.             {
  779.                /* Found it.  This relies on the fact that
  780.                ** no two MDI children can have the same
  781.                ** title.
  782.                */
  783.                EndDialog( hwndUnhide, ( int ) hwndIter );
  784.                return FALSE;
  785.             }
  786.          }
  787.  
  788.          /* No MDI child selected */
  789.          EndDialog( hwndUnhide, NULL );
  790.          break;
  791.       
  792.       case IDCANCEL:
  793.          EndDialog( hwndUnhide, NULL );
  794.          break;
  795.  
  796.       case DLGUNHIDE_LB:
  797.          /* Double click on list box same as OK */
  798.          if ( HIWORD( lParam ) == LBN_DBLCLK )
  799.          {
  800.             SendMessage( hwndUnhide, WM_COMMAND, IDOK, 0L );
  801.          }
  802.          break;
  803.       }
  804.       break;
  805.    }
  806.    return FALSE;
  807. }
  808.